package com.naonao.sns.qrcode;

import android.util.Log;
import android.os.Build;
import android.Manifest;
import android.util.Base64;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.content.Intent;
import android.content.Context;
import android.content.pm.PackageManager;

import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.apache.cordova.CallbackContext;
import org.json.JSONException;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.ArrayList;
import com.xys.libzxing.zxing.encoding.EncodingUtils;
import com.xys.libzxing.zxing.activity.CaptureActivity;

import com.naonao.sns.util.ResultFlag;

public class QRCodePlugin extends CordovaPlugin {

    public static final String TAG = "QRCodeLog-naonao";
    private static final int PERMISSON_REQUESTCODE = 55;
    private static final int QR_CODE = 60;
    private CallbackContext callbackContext = null;
    private String actionContext = null;
    private JSONArray argsContext = null;
    private Activity activity = null;
    private Context appContext = null;

	private static String[] needPermissions = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.CAMERA
    };

    private void createQRCodeImage(JSONArray args) throws JSONException {
        JSONObject result = new JSONObject();

        try{
            JSONObject param = (JSONObject)args.get(0);
            String content = param.getString("content");
            Integer black = Color.parseColor(param.getString("black"));
            Integer white = Color.parseColor(param.getString("white"));
            Integer width = Integer.parseInt(param.getString("width"));
            Integer height = Integer.parseInt(param.getString("height"));
            Float percent = Float.parseFloat(param.getString("percent"));
            Integer margin = Integer.parseInt(param.getString("margin"));
            Bitmap logo = null;

            if("".equals(content)) {
                throw new Exception();
            }

            if(!"".equals(param.getString("logo"))) {
                byte[] logoByte = Base64.decode(param.getString("logo"), Base64.DEFAULT);
                logo = BitmapFactory.decodeByteArray(logoByte, 0, logoByte.length);
            }

            Bitmap qrcodeImage = EncodingUtils.createQRCode(content, width, height,
                                                        logo, black, white, percent, margin);

            if(qrcodeImage != null) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                boolean flag = qrcodeImage.compress(Bitmap.CompressFormat.JPEG, 100, baos);
                baos.flush();
                baos.close();

                if(flag) {
                    byte[] qrcodeByte = baos.toByteArray();
                    result.put("qrcodeByte", Base64.encodeToString(qrcodeByte, Base64.DEFAULT));
                    returnDataToJs(result, ResultFlag.SUCCESS_CODE);
                }else {
                    returnDataToJs(result, ResultFlag.FAIL_CODE);
                }
            }else {
                returnDataToJs(result, ResultFlag.FAIL_CODE);
            }
        }catch(Exception e) {
            returnDataToJs(result, ResultFlag.ERROR_CODE);
        }
    }

    private void returnDataToJs(JSONObject obj, int code) throws JSONException {
        if(code == ResultFlag.SUCCESS_CODE) {
            obj.put("status", ResultFlag.SUCCESS_STATUS);
        }else if(code == ResultFlag.FAIL_CODE) {
            obj.put("status", ResultFlag.FAIL_STATUS);
        }else if(code == ResultFlag.ERROR_CODE) {
            obj.put("status", ResultFlag.ERROR_STATUS);
        }

        obj.put("code", code);
        PluginResult res = new PluginResult(PluginResult.Status.OK, obj);
        res.setKeepCallback(true);
        callbackContext.sendPluginResult(res);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        try{
            JSONObject result = new JSONObject();
            if(requestCode == QR_CODE && resultCode == activity.RESULT_OK) {
                String codeStr = intent.getStringExtra("result");
                result.put("codeStr", codeStr);

                returnDataToJs(result, ResultFlag.SUCCESS_CODE);
            }else if(requestCode == QR_CODE && resultCode == activity.RESULT_CANCELED) {
                returnDataToJs(result, ResultFlag.FAIL_CODE);
            }
        }catch(Exception e) {
            Log.e(TAG, e.toString());
        }
    }

    private void richScanQRCode(JSONArray args) {
        Intent intent = new Intent(activity, CaptureActivity.class);
        this.cordova.startActivityForResult(this, intent, QR_CODE);
    }

    private List<String> findDeniedPermissions(String[] permissions) {
        List<String> needRequestPermissonList = new ArrayList<>();
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            for(String perm: permissions) {
                if(appContext.checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
                    needRequestPermissonList.add(perm);
                }
            }
        }
        return needRequestPermissonList;
    }

    private void checkPermissions(String[] permissions) throws JSONException {
        List<String> needRequestPermissonList = findDeniedPermissions(permissions);
        if(null != needRequestPermissonList && needRequestPermissonList.size() > 0) {
            String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
            this.cordova.requestPermissions(this, PERMISSON_REQUESTCODE, array);
        }else{
            whatToExecute();
        }
    }

    private void whatToExecute() throws JSONException {
        try{
			if("createQRCodeImage".equals(actionContext)) {
				createQRCodeImage(argsContext);
			}else if("richScanQRCode".equals(actionContext)) {
				richScanQRCode(argsContext);
			}
        }catch(Exception e) {
            returnDataToJs(new JSONObject(), ResultFlag.ERROR_CODE);
        }
    }

    @Override
    public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults)
            throws JSONException {

        if(requestCode == PERMISSON_REQUESTCODE) {
            if(!verifyPermissions(grantResults)) {
                Log.e(TAG, "获取权限失败");
                returnDataToJs(new JSONObject(), ResultFlag.FAIL_CODE);
            }else {
                whatToExecute();
            }
        }
    }

    private boolean verifyPermissions(int[] grantResults) {
        for(int result: grantResults) {
            if(result != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callback)
            throws JSONException {

        callbackContext = callback;
        actionContext = action;
        argsContext = args;
        activity = this.cordova.getActivity();
        appContext = this.cordova.getContext();

        try{
            checkPermissions(needPermissions);
            return true;
        }catch(Exception e) {
            returnDataToJs(new JSONObject(), ResultFlag.ERROR_CODE);
        }

        return super.execute(action, args, callback);
    }
}
